﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Office.Server.Search.Query;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Taxonomy;
using TagCloud;

namespace spSitePro.TagCloudWP
{
	public class TagCloudHandler : IHttpHandler
	{
		#region [IHttpHandler implementation]

		public void ProcessRequest(HttpContext context)
		{
			try
			{
				int tagCount = 10;
				int.TryParse(context.Request[C.RequestParams.TagCount], out tagCount);

				string response = GenerateMarkup(tagCount,
														context.Request[C.RequestParams.RedirectUrlFormat],
														context.Request[C.RequestParams.TagToolTipFormat],
														context.Request[C.RequestParams.TermStoreName],
														context.Request[C.RequestParams.TermSetGroupName],
														context.Request[C.RequestParams.TermSetName],
														context.Request[C.RequestParams.SearchManagedPropertyName]
													);
				//throw new Exception("ha ha");
				context.Response.Write(response);

				context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(900));
				context.Response.Cache.SetLastModified(DateTime.Now);
				context.Response.Cache.SetCacheability(HttpCacheability.Public);
				context.Response.Cache.SetValidUntilExpires(true);
			}
			catch (Exception ex)
			{
				ErrorUtils.LogError(ex);

				context.Response.StatusDescription = string.Format("Error message: {0}", ex.Message);
				context.Response.StatusCode = 500;

				if (SPContext.Current.Web.CurrentUser != null && SPContext.Current.Web.CurrentUser.IsSiteAdmin)
				{
					context.Response.Write(string.Format("Error message: {0}", ex.Message));
					context.Response.Write("<br />");
					context.Response.Write(string.Format("Stack trace: {0}", ex.StackTrace));
				}
				else
				{
					context.Response.Write("Unexpected error has occured. Please contact your administrator.");
				}
			}
		}

		public bool IsReusable
		{
			get { return true; }
		}

		#endregion

		#region [Private Methods]

		private string GenerateMarkup(int tagCount,
										string redirectUrlFormat,
										string tagToolTipFormat,
										string termStoreName,
										string termSetGroupName,
										string termSetName,
										string searchManagedPropertyName)
		{
			SPSite siteCollection = SPContext.Current.Site;

			TermCollection terms = GetTerms(siteCollection, termStoreName, termSetGroupName, termSetName);

			var weightedTags = new Dictionary<string, int>();

			foreach (Term term in terms)
			{
				int usageNumber = CountTermUsage(siteCollection, searchManagedPropertyName, term.Name);

				weightedTags.Add(term.Name, usageNumber);
			}

			TagCloudGenerationRules rules = TagCloudGenerationRules.Default;
			rules.TagUrlFormatString = redirectUrlFormat;
			rules.MaxNumberOfTags = tagCount;
			rules.TagToolTipFormatString = tagToolTipFormat;

			TagCloud.TagCloud cloud = new TagCloud.TagCloud(weightedTags, rules);
			return cloud.ToString();
		}

		private TermCollection GetTerms(SPSite siteCollection,
										string termStoreName,
										string termSetGroupName,
										string termSetName)
		{
			TaxonomySession session = new TaxonomySession(siteCollection);

			TermStore termStore = session.TermStores[termStoreName];
			Group group = termStore.Groups.First(g => g.Name == termSetGroupName);
			TermSet termSet = group.TermSets[termSetName];

			return termSet.GetAllTerms();
		}

		private int CountTermUsage(SPSite siteCollection, string searchManagedPropertyName, string tag)
		{
			KeywordQuery keywordQuery = new KeywordQuery(siteCollection);
			keywordQuery.SelectProperties.Add(searchManagedPropertyName);
			keywordQuery.QueryText = string.Format("{0}=\"{1}\"", searchManagedPropertyName, tag);
			keywordQuery.ResultTypes = ResultType.RelevantResults;

			ResultTableCollection results = keywordQuery.Execute();
			ResultTable relevantResults = results[ResultType.RelevantResults];

			return relevantResults.Table.Rows.Count;
		}

		#endregion
	}
}
